﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ARR.DataModel.Repositories;
using ARR.Entities;
using DDF.Entity;
using ARR.Entities.Gateways;
using System.Transactions;

namespace ARR.Services.Domain
{
    public static class AttributesDomain
    {
        public static List<AttributeType> GetAllTypes()
        {
            var rows = AttributeTypesRepository.Select();
            var types = rows.ConvertAll<AttributeType>(att => new AttributeType(att));

            types.ForEach(type => type.ChangeState(EntityState.Original));

            return types;
        }

        public static List<Entities.Attribute> GetValuesForAttribute(int attributeTypeId)
        {
            var categories = CategoriesDomain.GetAll();

            var rows = AttributesRepository.Select(val => val.AttributeTypeId == attributeTypeId);
            var values = rows.ConvertAll<Entities.Attribute>(att => new Entities.Attribute(att));

            foreach (var val in values)
            {
                val.Category = categories.SingleOrDefault(x => x.Id == val.CategoryId);
                val.ChangeState(EntityState.Original);
            }


            return values;
        }

        public static List<AttributeType> GetAllTypesWithValues()
        {
            List<AttributeType> types = GetAllTypes();

            foreach (AttributeType type in types)
            {
                type.Values = GetValuesForAttribute(type.Id);
            }

            types.ForEach(type => type.ChangeState(EntityState.Original));

            return types;
        }

        public static List<Entities.Attribute> GetValuesForArticle(int articleId)
        {
            List<Entities.Attribute> attributes = new List<Entities.Attribute>();
            List<AttributeRow> allAttributeValues = AttributesRepository.Select();

            var rows = ArticleAttributesRepository.Select(aa => aa.ArticleId == articleId);


            var ArticleAttributes = from aa in rows
                                    join att in allAttributeValues on aa.AttributeId equals att.Id
                                    select new Entities.Attribute(att);


            return ArticleAttributes.ToList();
        }

        public static void Save(List<AttributeType> attributeTypes)
        {
            var typesToSave = attributeTypes.Where(x => x.GetEntityState() == EntityState.Modified || x.GetEntityState() == EntityState.New);

            using (TransactionScope scope = new TransactionScope())
            {
                foreach (var type in typesToSave)
                {
                    if (type.IsValid)
                    {
                        if (type.GetEntityState() == EntityState.New)
                        {
                            AttributeTypesRepository.Insert(type.GetRow());
                        }
                        else if (type.GetEntityState() == EntityState.Modified)
                        {
                            AttributeTypesRepository.Update(type.GetRow());
                        }

                        if (type.Values != null && type.Values.Any())
                        {
                            foreach (var value in type.Values)
                            {
                                value.AttributeTypeId = type.Id;

                                if (value.IsValid)
                                {
                                    if (value.GetEntityState() == EntityState.New)
                                    {
                                        AttributesRepository.Insert(value.GetRow());
                                    }
                                    else if (value.GetEntityState() == EntityState.Modified)
                                    {
                                        AttributesRepository.Update(value.GetRow());
                                    }
                                }
                                else
                                {
                                    throw new ARRException(string.Format("El valor {0} del atributo {1} es invalido.", value.AttributeValue, type.Name));
                                }
                            }
                        }
                    }
                    else
                    {
                        throw new ARRException(string.Format("El atributo {0} es invalido.", type.Name));
                    }
                }

                scope.Complete();
            }
        }
    }
}
